﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.Design;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;

namespace SCS.Web.UI.WebControls
{
    /// <summary>
    /// Represents a list item in the <see cref="HierList"/> WebControl.
    /// </summary>
    #region Class Attributes
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
    //[DefaultEvent("ButtonClicked"), DefaultProperty("Items")]    
    [ParseChildren(true, "Items")]
    [PersistChildren(false)]
    //[Designer(typeof(SCS.Web.UI.WebControls.Design.ToolbarDesigner))]
    #endregion
    public class HierListItem : IStateManager
    {
        #region Fields

        private HierList _root;
        private HierListItemCollection _items;

        private bool _isTrackingViewState = false;
        private StateBag _viewState;

        private bool _visible = true;
        private bool _enabled = true;
        private bool _selectable = true;
        private bool _selected = false;

        private string _id = "";
        private string _text = "";
        private string _value = "";
        private string _toolTip = "";
        private string _url = "";
        private string _target = "";
        
        private int _depth = 0;
        #endregion

        private object _dataItem;

        /// <summary>
        /// Gets the item's view state information.
        /// </summary>
        /// <value>The view state.</value>
        /// <remarks>This property is intended to only be used in custom control development.</remarks>
        protected StateBag ViewState
        {
            get
            {
                if (_viewState == null)
                {
                    _viewState = new StateBag(false);

                    if (_isTrackingViewState)
                        ((IStateManager)_viewState).TrackViewState();
                }
                return _viewState;
            }
        }
        internal void SetDirty()
        {
            if (_viewState != null)
            {
                ICollection Keys = _viewState.Keys;
                foreach (string key in Keys)
                {
                    _viewState.SetItemDirty(key, true);
                }
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="HierListItem"/> class.
        /// </summary>
        public HierListItem()
        {
        }

        internal void Render(HtmlTextWriter writer)
        {
            if (Visible)
            {
                writer.RenderBeginTag(HtmlTextWriterTag.Li);

                writer.AddAttribute(HtmlTextWriterAttribute.Id, ID);
                writer.AddAttribute(HtmlTextWriterAttribute.Title, ToolTip);

                string clickCode = "javascript:";

                if (Selectable && Enabled)
                {
                    if (string.IsNullOrEmpty(Url))
                    {
                        clickCode += ControlRoot.Page.ClientScript.GetPostBackEventReference(ControlRoot, Value);

                        writer.AddAttribute(HtmlTextWriterAttribute.Href, clickCode, false);
                    }
                    else
                    {
                        writer.AddAttribute(HtmlTextWriterAttribute.Href, Url);

                        if (!string.IsNullOrEmpty(Target))
                        {
                            writer.AddAttribute(HtmlTextWriterAttribute.Target, Target);
                        }
                    }
                }
                else
                {
                    clickCode += "{}";
                }

                if (!Enabled)
                {
                    writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled");
                }

                RenderAdditionalAttributes(writer);

                if (Enabled)
                {
                    writer.RenderBeginTag(HtmlTextWriterTag.A);
                }
                else
                {
                    writer.RenderBeginTag(HtmlTextWriterTag.Span);
                }
                
                RenderPreText(writer);
                writer.Write(Text);
                RenderPostText(writer);
                
                writer.RenderEndTag(); // close tag                
            }
        }

        /// <summary>
        /// Renders additional attributes into the HTML of the item.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <remarks>This property is intended to only be used in custom control development.</remarks>
        protected virtual void RenderAdditionalAttributes(HtmlTextWriter writer)
        {
        }
        /// <summary>
        /// Writes additional text prior to list item's text being written.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <remarks>This property is intended to only be used in custom control development.</remarks>
        protected virtual void RenderPreText(HtmlTextWriter writer)
        {
        }
        /// <summary>
        /// Writes additional text after list item's text has been written.
        /// </summary>
        /// <param name="writer">The writer.</param>
        /// <remarks>This property is intended to only be used in custom control development.</remarks>
        protected virtual void RenderPostText(HtmlTextWriter writer)
        {
        }

        #region IStateManager implementation

        /// <summary>
        /// When implemented by a class, gets a value indicating whether a server control is tracking its view state changes.
        /// </summary>
        /// <value></value>
        /// <returns>true if a server control is tracking its view state changes; otherwise, false.</returns>
        protected virtual bool IsTrackingViewState
        {
            get
            {
                return _isTrackingViewState;
            }
        }
        /// <summary>
        /// Loads the state of the view.
        /// </summary>
        /// <param name="savedState">State of the saved.</param>
        protected virtual void LoadViewState(object savedState)
        {
            if (savedState != null)
            {
                ((IStateManager)ViewState).LoadViewState(savedState);

                object text = ViewState["text"];

                if (text != null)
                    this.Text = (string)text;

                object value = ViewState["value"];

                if (value != null)
                    this.Value = (string)value;

                object url = ViewState["url"];

                if (url != null)
                    this.Url = (string)url;

                object target = ViewState["target"];

                if (target != null)
                    this.Target = (string)target;

                object tooltip = ViewState["tooltip"];

                if (tooltip != null)
                    this.ToolTip = (string)tooltip;

                object enabled = ViewState["enabled"];

                if (enabled != null)
                    this.Enabled = (bool)enabled;

                object visible = ViewState["visible"];

                if (visible != null)
                    this.Visible = (bool)visible;

                object selected = ViewState["selected"];

                if (selected != null)
                    this.Selected = (bool)selected;

                if (this.Selected)
                    this.ControlRoot.SelectedValue = this.Value;

                object items = ViewState["items"];

                if (items != null)
                {
                    this.Items.ControlRoot = _root;
                    ((IStateManager)this.Items).LoadViewState(items);
                }
            }
        }
        /// <summary>
        /// When implemented by a class, saves the changes to a server control's view state to an <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// The <see cref="T:System.Object"/> that contains the view state changes.
        /// </returns>
        protected virtual object SaveViewState()
        {
            string currentText = this.Text;
            string initialText = (ViewState["text"] == null) ? "" : (string)ViewState["text"];

            if (currentText.Equals(initialText) == false)
            {
                ViewState["text"] = currentText;
            }

            string currentValue = this.Value;
            string initialValue = (ViewState["value"] == null) ? "" : (string)ViewState["value"];

            if (currentValue.Equals(initialValue) == false)
            {
                ViewState["value"] = currentValue;
            }

            string currentUrl = this.Url;
            string initialUrl = (ViewState["url"] == null) ? "" : (string)ViewState["url"];

            if (currentUrl.Equals(initialUrl) == false)
            {
                ViewState["url"] = currentUrl;
            }

            string currentTarget = this.Target;
            string initialTarget = (ViewState["target"] == null) ? "" : (string)ViewState["target"];

            if (currentTarget.Equals(initialTarget) == false)
            {
                ViewState["target"] = currentTarget;
            }

            string currentTooltip = this.ToolTip;
            string initialTooltip = (ViewState["tooltip"] == null) ? "" : (string)ViewState["tooltip"];

            if (currentTooltip.Equals(initialTooltip) == false)
            {
                ViewState["tooltip"] = currentTooltip;
            }

          
            bool currentEnabled = this.Enabled;
            bool initialEnabled = (ViewState["enabled"] == null) ? true : (bool)ViewState["enabled"];

            if (currentEnabled.Equals(initialEnabled) == false)
            {
                ViewState["enabled"] = currentEnabled;
            }

            bool currentVisible = this.Visible;
            bool initialVisible = (ViewState["visible"] == null) ? true : (bool)ViewState["visible"];

            if (currentVisible.Equals(initialVisible) == false)
            {
                ViewState["visible"] = currentVisible;
            }

            bool currentSelected = this.Selected;
            bool initialSelected = (ViewState["selected"] == null) ? true : (bool)ViewState["selected"];

            if (currentSelected.Equals(initialSelected) == false)
            {
                ViewState["selected"] = currentSelected;
            }

            if (Items.Count > 0)
            {
                ViewState["items"] = ((IStateManager)Items).SaveViewState();
            }

            if (_viewState != null)
            {
                return ((IStateManager)_viewState).SaveViewState();
            }
            return null;
        }
        /// <summary>
        /// When implemented by a class, instructs the server control to track changes to its view state.
        /// </summary>
        protected virtual void TrackViewState()
        {
            if (Text.Length > 0)
                ViewState["text"] = _text;

            if (!string.IsNullOrEmpty(Value))
                ViewState["value"] = _value;

            if (Url.Length > 0)
                ViewState["url"] = _url;

            if (Target.Length > 0)
                ViewState["target"] = _target;

            if (ToolTip.Length > 0)
                ViewState["tooltip"] = _toolTip;

            if (Enabled != true)
                ViewState["enabled"] = Enabled;

            if (Visible != true)
                ViewState["visible"] = Visible;

            if (Selected != true)
                ViewState["selected"] = Selected;

            //if (Items.Count > 0)
            {
                ((IStateManager)Items).TrackViewState();
            }

            _isTrackingViewState = true;

            if (_viewState != null)
            {
                ((IStateManager)_viewState).TrackViewState();
            }
        }

        bool IStateManager.IsTrackingViewState
        {
            get
            {
                return IsTrackingViewState;
            }
        }
        void IStateManager.LoadViewState(object savedState)
        {
            LoadViewState(savedState);
        }
        object IStateManager.SaveViewState()
        {
            return SaveViewState();
        }
        void IStateManager.TrackViewState()
        {
            TrackViewState();
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the child items.
        /// </summary>
        /// <value>The child items.</value>
        [Category("Misc"), Description("The collection of list items."), Bindable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), NotifyParentProperty(true)]
        [PersistenceMode(PersistenceMode.EncodedInnerDefaultProperty)]
        public HierListItemCollection Items
        {
            get
            {
                if (_items == null)
                {
                    _items = new HierListItemCollection();
                    _items.ControlRoot = ControlRoot;

                    if (_isTrackingViewState)
                    {
                        ((IStateManager)_items).TrackViewState();
                    }
                }
                return _items;
            }
        }

        #region Appearance

        /// <summary>
        /// Gets or sets the item text.
        /// </summary>
        /// <value>The item text.</value>
        [Bindable(true), Category("Appearance"), DefaultValue(""), Themeable(false), Description("The text to display on the button.")]
        public string Text
        {
            get
            {
                return _text;
            }
            set
            {
                _text = value ?? "";
            }
        }

        #endregion

        #region Behavior

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="HierListItem"/> is enabled.
        /// </summary>
        /// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(true), Themeable(true), Description("Whether the item is enabled.")]
        public bool Enabled
        {
            get
            {
                return _enabled;
            }
            set
            {
                _enabled = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="HierListItem"/> is selectable.
        /// </summary>
        /// <value><c>true</c> if selectable; otherwise, <c>false</c>.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(true), Themeable(true), Description("Whether the item can be selected.")]
        public bool Selectable
        {
            get
            {
                return _selectable;
            }
            set
            {
                _selectable = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="HierListItem"/> is visible.
        /// </summary>
        /// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(true), Themeable(true), Description("The visibility of the button image.")]
        public bool Visible
        {
            get
            {
                return _visible;
            }
            set
            {
                _visible = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this <see cref="HierListItem"/> is selected.
        /// </summary>
        /// <value><c>true</c> if selected; otherwise, <c>false</c>.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(true), Themeable(true), Description("Whether the item is currently selected.")]
        public bool Selected
        {
            get
            {
                return _selected;
            }
            set
            {
                _selected = value;
            }
        }

        /// <summary>
        /// Gets or sets the tool tip.
        /// </summary>
        /// <value>The tool tip.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(""), Themeable(false), Description("The tooltip message to display.")]
        public string ToolTip
        {
            get
            {
                return _toolTip;
            }
            set
            {
                _toolTip = value ?? "";
            }
        }

        /// <summary>
        /// Gets or sets the URL.
        /// </summary>
        /// <value>The URL.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(""), Themeable(false), Description("The URL of the menu option.")]
        public string Url
        {
            get
            {
                return _url;
            }
            set
            {
                _url = value ?? "";
            }
        }

        /// <summary>
        /// Gets or sets the URL target.
        /// </summary>
        /// <value>The URL target.</value>
        [Bindable(true), Category("Behavior"), DefaultValue(""), Themeable(false), Description("The URL target.")]
        public string Target
        {
            get
            {
                return _target;
            }
            set
            {
                _target = value ?? "";
            }
        }
        #endregion

        /// <summary>
        /// Gets or sets the ID.
        /// </summary>
        /// <value>The ID.</value>
        [Bindable(false), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal string ID
        {
            get
            {
                return _id;
            }
            set
            {
                _id = value ?? "";
            }
        }

        /// <summary>
        /// Gets or sets the depth.
        /// </summary>
        /// <value>The depth.</value>
        [Bindable(false), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal int Depth
        {
            get
            {
                return _depth;
            }
            set
            {
                _depth = value;
            }
        }

        /// <summary>
        /// Gets or sets the control root.
        /// </summary>
        /// <value>The control root.</value>
        [Bindable(false), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        internal HierList ControlRoot
        {
            get
            {
                return _root;
            }
            set
            {
                _root = value;
            }
        }

        /// <summary>
        /// Gets or sets the value.
        /// </summary>
        /// <value>The value.</value>
        [Bindable(false), Category("Misc"), DefaultValue(""), Themeable(false), Description("The value of the list item.")]
        public string Value
        {
            get
            {
                return _value;
            }
            set
            {
                _value = value ?? "";
            }
        }

        //[Bindable(false), Browsable(false), DefaultValue(""), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        //public string DataPath
        //{
        //    get
        //    {
        //        object obj2 = this.ViewState["DataPath"];
        //        if (obj2 == null)
        //        {
        //            return string.Empty;
        //        }
        //        return (string)obj2;
        //    }
        //}

        #endregion
         
        internal void SetDataItem(object dataItem)
        {
            this._dataItem = dataItem;
        }
        internal void SetDataPath(string dataPath)
        {
            this.ViewState["DataPath"] = dataPath;
        }
        internal void SetDataBound(bool dataBound)
        {
            this.ViewState["DataBound"] = dataBound;
        }
    }
}
